package demo13


import "fmt"

// 桥接模式分离抽象部分和实现部分。使得两部分独立扩展。
// 桥接模式类似于策略模式，区别在于策略模式封装一系列算法使得算法可以互相替换。
// 策略模式使抽象部分和实现部分分离，可以独立变化。

// --------------------------------场景1-----------------------------------
// AbstractMessage | MessageImplementer | MessageSMS | ViaSMS | MessageEmail | ViaEmail | CommonMessage | NewCommonMessage | 
// UrgencyMessage | NewUrgencyMessage | SendMessage | 
// 先来看看官方的案例:
// 理论：将抽象和实例分离，抽象+===>接口  实例====>接口的实现====>变成抽像接口===> 两个接口， 两个接口就是独立的，实现抽象和实例分离独立
// 分析一个官方的案例：官方的表达是实现发送通信，那么发送通信的实例有两种，1.通过SMS 2.通过Email 这两种来实现，本应该两种都属于通信的实例
// 这里将实例抽离成接口，与原来的通信类组合

// 通信类
type AbstractMessage interface{
	SendMessage(text,to string)
}
// 抽象的通信接口
type MessageImplementer interface{
	Send(text, to string)
}

//  与其说与策略相似，反而觉得更像适配器模式 但是原理不一样【整体类似适配器】，
// 实例的方法 这里类似策略模式，提供不同的选择【内置确类似策略】

type MessageSMS struct{}
func ViaSMS() MessageImplementer{
	return &MessageSMS{}
}
func (MessageSMS)Send(text,to string){
	fmt.Println("发送信息内容:",text,"到",to)
}

type MessageEmail struct{}
func ViaEmail() MessageImplementer{
	return &MessageEmail{}
}
func (MessageEmail)Send(text,to string){
	fmt.Println("发送邮件内容:",text,"到",to)
}

// 类的实例
type CommonMessage struct{
	method MessageImplementer
}
func NewCommonMessage(method MessageImplementer) AbstractMessage{
	return &CommonMessage{
		method:method,
	}
}
func (c CommonMessage)SendMessage(text,to string){
	c.method.Send(text,to)
}

// 同上
type UrgencyMessage struct{
	method MessageImplementer
}
func NewUrgencyMessage(method MessageImplementer)AbstractMessage{
	return &UrgencyMessage{
		method:method,
	}
}
func (u UrgencyMessage)SendMessage(text, to string){
	u.method.Send(text,to)
}

// --------------------------------场景2-----------------------------------

// 需求 ：画笔画圆
// 分析：画笔可以画不同颜色圆，画笔和圆的关系
// 领域风暴: 画笔-对应->实例--抽象-->画笔接口[很多画笔],圆-对应->实例--抽象--->圆类接口[很多圆]
// 领域分析：画笔:Brush 画圆DrawCircle[花园需要的画什么的圆] 画笔|| 圆：Shape  红色的圆:RedCircle 蓝色的圆:BlueCircle 形状:Circle
// 这样做的好处就是OOP 和解耦
type Brush interface{
	// 多大的圆
	DrawCircle(x, y int)
}
// 这里注意两个方法相似【参数】，为了实例之间的桥接用的，
type Shape interface{
	Circle(x,y int)
}

// 实例
type RedCircle struct{}
func NewRedCircle() Shape{
	return &RedCircle{}
}
func (RedCircle)Circle(x,y int){ fmt.Println("红色的圆圈:大小是::",x,"::",y) }

type BlueCircle struct{}
func NewBlueCircle() Shape{
	return &BlueCircle{}
}
func (BlueCircle)Circle(x,y int){ fmt.Println("蓝色的圆圈:大小是::",x,"::",y) }

// 画笔 | 铅笔
type Pencil struct{
	shap Shape
}
func NewPencil(shap Shape) Brush{
	return &Pencil{
		shap:shap,
	}
}
func (p Pencil)DrawCircle(x,y int){ p.shap.Circle(x,y) }

// 画笔 | crayon
type Caryon struct{
	shap Shape
}
func NewCaryon(shap Shape)Brush{
	return &Caryon{
		shap:shap,
	}
}
func (c Caryon)DrawCircle(x,y int){ c.shap.Circle(x,y) }

// --------------------------------场景3-----------------------------------
// 需求：切换不同的类目，展示不同的信息
// 分析：不同的类目 <======> 不同的信息
// DDD : Items ["template"]  ShowTemplate(type) < ======= > infos  ["hots","recommend"] Template(type)
// 

type Items interface{ // 类目
	ShowTemplate(string)	// 款式
}
type infos interface{	// 款式信息
	Template(string)	// 款式类型
}

// 款式实例
type hots struct{}
func NewHots() infos{ return &hots{} }
func (hots)Template(name string){ fmt.Println("热卖款式类型:",name) }

type recommend struct{}
func NewRecommend() infos { return &recommend{} }
func (recommend)Template(name string) { fmt.Println("推荐款式类型:",name) }

// 类目
type menu struct{
	info infos
}
func NewMenu(info infos) Items{
	return &menu{
		info:info,
	}
}
func (m menu)ShowTemplate(name string) { m.info.Template(name) }

// --------------------------------场景4-----------------------------------
// 总结桥接模式
// 通过以上的案例总计出来，首先就是关于抽象和实例的分离.个人亲觉得其次也算是OOP的思想
// 通过聚合来的抽象实例，然后根据不同的实例来调用实现，那么如果在写业务逻辑的时候，某区域的逻辑业务功能相似的话
// 那么可以使用上一层抽象起来封装，然后给外部调用，
// 桥接模式和适配器模式不同的地方
// 桥接模式是实现抽象和实例分离的封装，适配器仅仅是两个接口之间的转换
// 桥接模式策略模式不同的地方
// 策略模式时面向结构体，桥接是面向抽象接口
